package com.usian.filter;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.usian.pojo.User;
import com.usian.utils.JWTUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.*;


/**
 * security + jwt 生成token 过滤器 工具类
 */
@Component
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private  AuthenticationManager authenticationManager;

    public TokenLoginFilter(AuthenticationManager authenticationManager){
        this.authenticationManager = authenticationManager;
    }


    //把security 中登录获得用户对象 封装到  AuthenticationManager 对象中  显示初始化
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        User sysUser = null;
        try {
            String json =getJson(request);
            if(json.contains("&")){
                Map parameters = this.getParameters(json);
                json = JSON.toJSONString(parameters);
            }
            sysUser = JSON.parseObject(json, User.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword());
        this.setDetails(request, authRequest);
        return authenticationManager.authenticate(authRequest);
    }



    //把请求体中的参数序列化
    public String getJson(HttpServletRequest request) throws IOException {
        BufferedReader streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), "UTF-8"));
        StringBuilder sb = new StringBuilder();
        String inputStr;
        while ((inputStr = streamReader.readLine()) != null) {
            sb.append(inputStr);
        }
        return sb.toString();
    }


    //认证成功 生成token  可改动  username
    protected void successfulAuthentication(HttpServletRequest request
            , HttpServletResponse response
            , FilterChain chain
            , Authentication authResult) throws IOException, ServletException {
        // 获取用户信息
        Map<String,String> map = new HashMap<>();
        map.put("username",authResult.getName());
        Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();


        //用户权限重新遍历放到统一json字符串中
        List<String> list = new ArrayList<>();
        for (GrantedAuthority authority : authorities) {
            list.add(authority.getAuthority());
        }
        map.put("roles", JSON.toJSONString(list));

        //生成Token信息
        String token = JWTUtils.getToken(map);
        response.addHeader("Authorization",token);
        try {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = response.getWriter();
            Map<String,Object> resultMap = new HashMap();
            resultMap.put("code", HttpServletResponse.SC_OK);
            resultMap.put("msg", "认证通过！");
            out.write(JSON.toJSONString(resultMap));
            out.flush();
            out.close();
        }catch (Exception outEx){
            outEx.printStackTrace();
        }
    }

    //认证失败  401
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        try {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            PrintWriter out = response.getWriter();
            Map resultMap = new HashMap();
            resultMap.put("code", HttpServletResponse.SC_UNAUTHORIZED);
            resultMap.put("msg", "用户名或密码错误！");
            out.write(new ObjectMapper().writeValueAsString(resultMap));
            out.flush();
            out.close();
        }catch (Exception outEx){
            outEx.printStackTrace();
        }
    }

    @Autowired
    @Override
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        super.setAuthenticationManager(authenticationManager);
    }


    /**
     * get 请求参数 转json串工具类  
     * 比如 username=boge&password=1234 把该url传进来得到
     * {"username":"boge","password":"1234"}   可通用
     * 
     * @param url
     * @return
     */
    public Map getParameters(String url) {
        Map parameters = new HashMap<>();
        try {
            //String[] parts = url.split("\\?");
            //String query = parts[1];
            for (String parameter : url.split("&")) {
                String[] pair = parameter.split("=");
                String key = URLDecoder.decode(pair[0], "UTF-8");
                String value = URLDecoder.decode(pair[1], "UTF-8");
                parameters.put(key, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return parameters;
    }
}
